use axum::{headers::Cookie, http::{self, HeaderMap, HeaderValue}, response::IntoResponse, Extension, TypedHeader, Json};
use axum::response::Response;
use rbatis::Uuid;
use serde::{Deserialize, Serialize};
use serde_json::json;
use tracing::error;
use validator::Validate;

use cores::{responses::CusResponse, sessions::{Session, SessionData}, validator::ValidatedJson, secret::pbkdf2_secret, Result, AppError};
use config::CONFIG;
use cores::secret::pbkdf2_secret_verify;
use cores::validator::ValidatedQuery;
use crate::dao::{AuthClient, User};
use crate::middleware::UserAuthMiddleware;
use crate::service::*;

#[derive(Debug, Deserialize, Validate, Serialize)]
pub struct LoginForm {
    username: String,
    password: String,
}

#[derive(Debug, Deserialize, Validate, Serialize)]
pub struct RegistryForm {
    username: String,
    password: String,
}


pub async fn registry(
    ValidatedJson(registry_form): ValidatedJson<RegistryForm>,
) -> Result<User> {
    registry_service(
        registry_form.username,
        pbkdf2_secret(registry_form.password, CONFIG.read().await.secret().to_string())?,
    ).await
}

pub async fn login(
    ValidatedJson(login_form): ValidatedJson<LoginForm>,
    Extension(session): Extension<Session>,
) -> Result<impl IntoResponse> {
    // 创建请求头
    let mut headers = HeaderMap::new();
    // 创建缓存数据
    let mut session_data = SessionData::new();
    // 存储缓存数据
    let user = fetch_user_by_username(login_form.username).await?;
    if pbkdf2_secret_verify(login_form.password, user.password.unwrap(), CONFIG.read().await.secret().to_string()).is_err() {
        return Err(AppError::from_str("密码错误", 403));
    }
    session_data.insert(
        "user_id".to_string(),
        user.id.unwrap().to_string(),
    );
    // 存储session并获取cookie键名键值
    let cookie_value = session.set_session_data(session_data).await;
    // 将cookie放入请求头
    headers.insert(
        http::header::SET_COOKIE,
        HeaderValue::from_str(&cookie_value).unwrap(),
    );
    Ok((headers, CusResponse::ok("ok".to_string())))
}

#[derive(Debug, Serialize)]
pub struct UserInfo {
    id: String,
}

impl IntoResponse for UserInfo {
    fn into_response(self) -> Response {
        CusResponse::ok(self).into_response()
    }
}

pub async fn valid_session(
    TypedHeader(cookie): TypedHeader<Cookie>,
    Extension(session): Extension<Session>,
) -> Result<UserInfo> {
    let session_data = session.get_session_data(cookie).await?;
    let user_id = session_data.get("user_id")?;
    Ok(UserInfo {
        id: user_id
    })
}


#[derive(Debug, Deserialize, Validate, Serialize)]
pub struct RegistryApplicationForm {
    client_name: String,
    client_icon: String,
    redirect_url: String,
}

pub async fn registry_application(
    UserAuthMiddleware(user): UserAuthMiddleware,
    ValidatedJson(registry_application_form): ValidatedJson<RegistryApplicationForm>,
) -> Result<AuthClient> {
    registry_application_service(
        registry_application_form.client_name,
        registry_application_form.client_icon,
        registry_application_form.redirect_url,
        user,
    ).await
}

pub async fn get_my_application_list(
    UserAuthMiddleware(user): UserAuthMiddleware,
) -> impl IntoResponse {
    let apps = get_applications_by_user(user).await;
    CusResponse::ok(
        apps
    )
}

pub async fn get_my_auth_application_list(
    UserAuthMiddleware(user): UserAuthMiddleware,
) -> impl IntoResponse {
    let apps = get_auth_applications_by_user(user).await;
    CusResponse::ok(
        apps
    )
}


#[derive(Debug, Deserialize, Validate, Serialize)]
pub struct GenApplicationSecretQuery {
    id: Uuid,
}

pub async fn gen_application_secret_key(
    UserAuthMiddleware(user): UserAuthMiddleware,
    ValidatedQuery(query): ValidatedQuery<GenApplicationSecretQuery>,
) -> Result<AuthClient> {
    gen_application_secret_key_service(query.id.to_string(), user).await
}
